#ifndef	_USTC_USB_SCSI_H_
#define _USTC_USB_SCSI_H_

#ifndef AP_USB_FIXBUG
#define AP_USB_FIXBUG
#endif

/*
// RBC commands
*/
#define RBC_CMD_FORMAT						0x04
#define RBC_CMD_READ10						0x28
//for test
#define RBC_CMD_TEST						0x75

#define RBC_CMD_READCAPACITY				0x25
#define RBC_CMD_STARTSTOPUNIT				0x1B
#define RBC_CMD_SYNCCACHE					0x35
#define RBC_CMD_VERIFY10					0x2F
#define RBC_CMD_WRITE10						0x2A

/*
// SPC-2 commands
*/
#define SPC_CMD_INQUIRY						0x12
#define SPC_CMD_MODESELECT6					0x15
#define SPC_CMD_MODESENSE6					0x1A
#define SPC_CMD_PERSISTANTRESERVIN			0x5E
#define SPC_CMD_PERSISTANTRESERVOUT			0x5F
#define SPC_CMD_PRVENTALLOWMEDIUMREMOVAL	0x1E
#define SPC_CMD_RELEASE6					0x17
#define SPC_CMD_REQUESTSENSE				0x03
#define SPC_CMD_RESERVE6					0x16
#define SPC_CMD_TESTUNITREADY				0x00
#define SPC_CMD_WRITEBUFFER					0x3B
#define SPC_CMD_READLONG					0x23

/*cdrom class need*/
#define SPC_CMD_MODESENSE10 				0x5A
#define	SPC_CMD_READTOC						0x43

/*vendor specified scsi commands*/
#define	VENDOR_CMD_GET_INFO					0xf1
#define	VENDOR_CMD_SET_INFO					0xf2
#define	VENDOR_CMD_GET_VER					0xf3


#define VPDPAGE_SERIAL_NUMBER   0x80
#define VPDPAGE_DEVICE_IDENTITY 0x83


#define USB_SECURITY  0
#define USB_BOOT  1

#define BOOT_ACCESS_BYTE  0
#define BOOT_ACCESS_HALFWORD  1
#define BOOT_ACCESS_LONG  2

//set info
#define BOOT_WRITE_SINGLE  0x10
#define BOOT_LOAD  0x13
#define BOOT_DO  0x14
#define BOOT_RUN  0x15
#define BOOT_TEST  0x16

//
// INQUIRY Command
//
typedef PACKED_REMOVED struct  {
	USTC_U8 OperationCode;	//12h
	unsigned EnableVPD:1 ;
    unsigned CmdSupportData:1 ;
	unsigned Reserved0:6 ;
	USTC_U8 PageCode;
	USTC_U8 Reserved1;
	USTC_U8 AllocationLen;
    USTC_U8 Control;
} SPC_INQUIRY_T, *PSPC_INQUIRY_T;

typedef PACKED struct _STD_INQUIRYDATA {
    unsigned DeviceType : 5;
    unsigned Reserved0 : 3;

    unsigned Reserved1 : 7;
    unsigned RemovableMedia : 1;

    USTC_U8 Reserved2;

    unsigned Reserved3 : 5;
    unsigned NormACA : 1;
    unsigned Obsolete0 : 1;
    unsigned AERC : 1;

    USTC_U8 Reserved4[3];

    unsigned SoftReset : 1;
    unsigned CommandQueue : 1;
	unsigned Reserved5 : 1;
	unsigned LinkedCommands : 1;
	unsigned Synchronous : 1;
	unsigned Wide16Bit : 1;
	unsigned Wide32Bit : 1;
	unsigned RelativeAddressing : 1;

	USTC_U8 VendorId[8];

	USTC_U8 ProductId[16];

	USTC_U8 ProductRevisionLevel[4];

/*
//  Above is 36 bytes
//  can be tranmitted by Bulk
*/

    USTC_U8 VendorSpecific[20];
    unsigned InfoUnitSupport : 1;
    unsigned QuickArbitSupport : 1;
    unsigned Clocking : 2;
    unsigned Reserved6 : 4;

    USTC_U8  Reserved7 ;
    USTC_U16 VersionDescriptor[8] ;

    USTC_U8 Reserved8[22];
} STD_INQUIRYDATA_T, *PSTD_INQUIRYDATA_T;


/*
// Read Capacity Data - returned in Big Endian format
*/
typedef PACKED_REMOVED struct  {
    USTC_U8 LBA_3;
    USTC_U8 LBA_2;
    USTC_U8 LBA_1;
    USTC_U8 LBA_0;

    USTC_U8 BlockLen_3;
    USTC_U8 BlockLen_2;
    USTC_U8 BlockLen_1;
    USTC_U8 BlockLen_0;
} READ_CAPACITY_DATA_T, *PREAD_CAPACITY_DATA_T;

/*
// Read Capacity command
*/
typedef PACKED_REMOVED struct  {
	USTC_U8                OperationCode;	/* 10H */
	READ_CAPACITY_DATA_T  	CapData;       /* Reserved area, here is used as temp*/
	USTC_U8                Control;
}READ_CAPACITY_RBC_T, *PREAD_CAPACITY_RBC_T;

/*
// Read Command
*/
typedef PACKED struct  {
	USTC_U8 OperationCode;	//28H 
	unsigned RelAdr	: 1;
	unsigned Resv1	: 2;
	unsigned 	FUA	: 1;
	unsigned	DPO	: 1;
	unsigned	lun	: 3;
	
    PACKED union{
        PACKED struct
        {
	        USTC_U8 LBA_3;
	        USTC_U8 LBA_2;
	        USTC_U8 LBA_1;
	        USTC_U8 LBA_0;
        } LBA_W8;
       	USTC_U32 LBA_W32;
    }LBA;
	USTC_U8 Reserved;
	USTC_U8 transfer_len_hi;
	USTC_U8 transfer_len_lo;
	USTC_U8 resv2;
	USTC_U16	resv3;
}SPC_READ10_T, *PSPC_READ10_T;

/*
// Read Command
*/
typedef PACKED struct  {
	USTC_U8 OperationCode;	//2aH 
	unsigned Reserved0 : 3;
	unsigned FUA : 1;
	unsigned Reserved1 : 4;
	
    PACKED union{
        PACKED struct
        {
	        USTC_U8 LBA_3;
	        USTC_U8 LBA_2;
	        USTC_U8 LBA_1;
	        USTC_U8 LBA_0;
        } LBA_W8 ;
       	USTC_U32 LBA_W32;
    }LBA;
	USTC_U8 Reserved;
	USTC_U8 transfer_len_hi;
	USTC_U8 transfer_len_lo;
	USTC_U8 resv2;
	USTC_U16	resv3;
} SPC_WRITE10_T, *PSPC_WRITE10_T;

typedef PACKED struct  {
	USTC_U8 OperationCode;
	USTC_U8 Reserved[15];
} GENERIC_CDB_T,*PGENERIC_CDB_T;

#if 0
typedef PACKED struct  {
	USTC_U8 OperationCode;	//0xf1	
	USTC_U8	resv1;
	
	USTC_U8 src;	//0 SD 1 NF 2 Host; if not exists; return all zero
	USTC_U8 info_type;
	USTC_U8 resv2[8];
} CDB_VENDOR_GET_INFO_T;

typedef PACKED struct  {
	USTC_U8 OperationCode;	//0xf2	
	USTC_U8	resv1;
	
	USTC_U8 src;	//0 SD 1 NF 2 Host; if not exists; return all zero
	USTC_U8 info_type;
	USTC_U8 resv2[8];
} CDB_VENDOR_SET_INFO_T;
#else
typedef PACKED struct  {
	USTC_U8   OperationCode;	//0xf1	
	USTC_U8   cmdclass;
	USTC_U8   subcmd;//change from 'src'
	USTC_U8   info_type;
	USTC_U32 address;
	USTC_U8   value[4];
} CDB_VENDOR_GET_INFO_T;

typedef PACKED struct  {
	USTC_U8   OperationCode;	//0xf1	
	USTC_U8   cmdclass;
	USTC_U8   subcmd;//change from 'src'
	USTC_U8   info_type;
	USTC_U32 address;
	USTC_U32 value;
} CDB_VENDOR_SET_INFO_T;
#endif

typedef PACKED_REMOVED union {
    GENERIC_CDB_T             Cdb_Generic;
  
    //
    // SPC-2 commands
    //
    SPC_INQUIRY_T             Spc_Inquiry;
    SPC_READ10_T		    Spc_Read;
    SPC_WRITE10_T		    Spc_Write;
 	CDB_VENDOR_GET_INFO_T	vendor_get_info;
	CDB_VENDOR_SET_INFO_T	vendor_set_info;
} CDB, *PCDB;



int scsi_handler(void);

int spc_inquiry(void);
int spc_read_format_capacities(void);
int rbc_read_capacity(void);
int spc_read10(void);
int spc_mode_sense6(void);
int spc_test_unit_ready(void);
int spc_verify10(void);
int spc_write10(void);
int spc_prevent_remove(void);
int spc_mode_sense10(void);
int vendor_get_info(void);
int vendor_get_ver(void);
int spc_read_toc(void);
int vendor_set_info(void);

void scsi_check_disk_src(USTC_U8 lun);

void process_usbboot_cmd(USTC_U8 cmd_index, USTC_U8 para,USTC_U32 addr,USTC_U32 val);
#endif
